# !/usr/bin/env python
import os
import time
import signal
import traceback
from multiprocessing import Process, sharedctypes


def process_work(*args, **kwargs):
    while True:
        print(args)
        print(kwargs)
        print(os.getpid())
        print(os.getppid())
        print("=-=-=-=-=-=-")
        time.sleep(2)


class MultiProcessManager(object):
    _instance = None
    _init_end = False

    message = sharedctypes.Value('i', 1)

    def __new__(cls, *args, **kwargs):
        """
        :param args:
        :param kwargs:
        """
        if cls._instance is None:
            cls._instance = object.__new__(cls)
        return cls._instance

    def __init__(self, *args, **kwargs):
        if not MultiProcessManager._init_end:
            self.__process_dict = {}
            MultiProcessManager._init_end = True
            print(args)
            print(kwargs)

    @classmethod
    def get_instance(cls, *args, **kwargs):
        """
        获取实例
        :return: MultiprocessManagement
        """
        if not cls._instance:
            cls._instance = cls(*args, **kwargs)
        return cls._instance

    def creat_process(self, name, *args, function=None, **kwargs):
        """
        创建进程
        :return:
        """
        if name in self.__process_dict:
            return self.__process_dict[name]
        if function:
            new_process = Process(target=function, args=args, kwargs=kwargs, daemon=True)
        else:
            new_process = Process(target=self.process_function, args=(MultiProcessManager.message, *args),
                                  kwargs=kwargs, daemon=True)
        self.__process_dict[name] = new_process
        new_process.start()
        return new_process

    def process_function(self, message, *args, **kwargs):
        """
        进程方法
        :param message:
        :param args:
        :param kwargs:
        :return:
        """
        message.value = 2
        while True:
            print(
                f"message:{message.value},args:{args},MultiProcessManager_id:{id(MultiProcessManager)}"
                f"self_id:{id(self)},self.message:{self.message.value}")
            time.sleep(2)
            self.message.value = 8

    def destroy(self):
        """
        销毁所有进程
        """
        for process in list(self.__process_dict.values()):
            try:
                os.kill(process.pid, signal.SIGTERM)
                process.join()
                print(f" kill process {process.pid} success !!!!!!")
            except Exception:
                print(f"kill process: {process.pid} failed, {traceback.format_exc()}")
        self.__process_dict.clear()

    def destroy_process(self, process_name: str):
        """
        销毁指定的进程
        :param process_name: 进程名称
        """
        if process_name in self.__process_dict:
            process = self.__process_dict.pop(process_name)
            try:
                if os.name == 'nt':
                    os.kill(process.pid, signal.SIGINT)
                else:
                    os.kill(process.pid, signal.SIGKILL)
                process.join()
            except Exception:
                print(f"kill process: {process.pid} failed, {traceback.format_exc()}")

    def get_process_info(self, process=None):
        """
        获取进程ID
        :param process:
        :return:
        """

        for process_name in self.__process_dict:
            print(self.__process_dict[process_name].pid)
            print(self.__process_dict[process_name].name)
            print(self.__process_dict[process_name].is_alive())
            print("-------------------------------------------")


if __name__ == '__main__':
    mpm = MultiProcessManager("ssss", "sss", ssd="fg")
    mpm1 = MultiProcessManager()
    mpm2 = MultiProcessManager.get_instance("ssss", "sss", ssd="fg")
    mpm.creat_process("1", "1", ingg="ddd")
    mpm.creat_process("2", "2", ingg="ddd")
    while True:
        print(MultiProcessManager.message.value)
        print(id(MultiProcessManager))
        time.sleep(2)
        MultiProcessManager.message.value = 3
